﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Windows.Forms;
using XFControls;
using XFControls.Utils;
using XFControls.XFPanels;
using XFControls.XFPanels.XFPanelItems;
using XFSenseUI.XFItems.SenseControls;

namespace XFSenseUI.XFItems
{
    public sealed class SenseItemDropDown : SenseItemBase
    {
        public SenseControlDropDown Control = new SenseControlDropDown();
        private XFPanelContainer _dropDownContainer;
        private bool _dropDownOpen;
        private SenseDropDownPanel _dropDownPanel;
        private int _height;
        private Rectangle _descRec;
        private int _linespace = 5;

        public SenseItemDropDown()
        {
            Options = new List<string>();
            int width = GetWidth();
            int padding = (width - Control.GetWidth()) >> 1;

            Style = new XFItemStyle
                    {
                        BorderBottomColor = Color.FromArgb(189, 182, 189),
                        DashStyleBottom = DashStyle.Dash,
                        TextColor = Color.Black,
                        TextFont = new Font(FontFamily.GenericSansSerif, 8, FontStyle.Regular),
                        SelectedTextFont = new Font(FontFamily.GenericSansSerif, 8, FontStyle.Regular),
                        SecondaryTextFont = new Font(FontFamily.GenericSansSerif, 7, FontStyle.Regular),
                        SelectedSecondaryTextFont = new Font(FontFamily.GenericSansSerif, 7, FontStyle.Regular),
                        SecondaryTextColor = Color.FromArgb(57, 52, 57),
                        SelectedTextColor = Color.White,
                        SelectedBackgroundColor = Color.FromArgb(43, 36, 43),
                        SelectedSecondaryTextColor = Color.FromArgb(182, 178, 182),
                        Padding = padding,
                        PaddingTop = 10,
                        PaddingBottom = 10,
                    };

            ItemType = XFItemType.ClickableNonChange;


            var rec = new Rectangle();
            _dropDownPanel = new SenseDropDownPanel(rec);
            _dropDownContainer = new XFPanelContainer();

            _dropDownPanel.BackColor = Color.White;
            _dropDownPanel.ShowScrollbar(true);
            _dropDownPanel.ScrollbarColor = Color.Gray;
            _dropDownPanel.OnSelection += (o, e) =>
            {
                Selected = e.Text;
                if (SelectionChanged != null)
                    SelectionChanged(o, e);

                if (Parent is XFPanelList)
                    ((XFPanelList)Parent).OnBlur();
                else
                    OnBlur();
            };

            _dropDownContainer.SetMainPanel(_dropDownPanel);
        }

        public List<string> Options { get; set; }

        public string Selected
        {
            get { return Control.Text; }
            set { Control.Text = value; }
        }

        public string Description { get; set; }
        public event SenseDropDownPanel.TextEventHandler SelectionChanged;

        public override void OnMouseDown(int x, int y)
        {
            base.OnMouseDown(x, y);
            Control.OnMouseDown(x, y);
        }

        public override void OnMouseMove(int x, int y)
        {
            Control.OnMouseMove(x, y);
        }

        public override void OnMouseUp()
        {
            Control.OnMouseUp();
        }

        public override void OnFocus()
        {
            SetupPanel();
            if (Parent != null)
            {
                int yCont = GetHeight() + Style.PaddingBottom;
                if (Parent is XFPanelList)
                {
                    int paddingTop = Style.PaddingTop;
                    if (!string.IsNullOrEmpty(Description))
                        paddingTop += _descRec.Height + _linespace;

                    int locY = ((XFPanelList)Parent).MakeItemVisible(this, _dropDownContainer.Height + yCont);
                    _dropDownContainer.Location = new Point(_dropDownContainer.Location.X, _dropDownContainer.Location.Y + Math.Abs(locY) + paddingTop);

                    var effect = new SenseControlDropDownEffect(_dropDownContainer.Height + yCont, locY, paddingTop, Control.Text);
                    Parent.AddEffect(effect);
                }
                Application.DoEvents();

                if (Parent.Parent is XFPanelContainer)
                {
                    Parent.Parent.Controls.Add(_dropDownContainer);
                    _dropDownContainer.BringToFront();
                }
            }
            Control.OnFocus();
        }

        public override void OnBlur()
        {
            _dropDownOpen = false;
            if (Parent != null)
            {
                if (Parent.Controls.Contains(_dropDownContainer))
                    Parent.Parent.Controls.Remove(_dropDownContainer);

                _dropDownContainer.Height = 0;
            }
            Control.OnBlur();

            Invalidate(true);

            if (Parent != null) Parent.Invalidate();
        }

        public override void OnScreenResize()
        {
            Control.OnScreenResize();
            throw new NotImplementedException();
        }

        public override int GetHeight()
        {
            if (_height > 0)
                return _height;

            if (!string.IsNullOrEmpty(Description))
            {
                _descRec = new Rectangle(0, 0, GetWidth() - (Style.PaddingLeft + Style.PaddingRight), 0);
                int height = Style.SecondaryTextFont.MeasureString(Description, _descRec).Height;
                _descRec.Height = height;
            }

            _height = Control.GetHeight() + Style.PaddingTop + Style.PaddingBottom + _descRec.Height + _linespace;

            if (Buffer == null)
                Buffer = XFBitmapFactory.GetBitmap(GetWidth(false), _height);

            return _height;
        }

        public override void ResetHeight()
        {
            _height = -1;
        }

        public override void ItemPaint(Graphics g, int x, int y)
        {
            base.ItemPaint(g, x, y);
            int localY = y + Style.PaddingTop;
            int localX = x + Style.PaddingLeft;

            if (!string.IsNullOrEmpty(Description))
            {
                _descRec.X = localX;
                _descRec.Y = localY;
                using (var b = new SolidBrush(Style.SecondaryTextColor))
                    g.DrawString(Description, Style.SecondaryTextFont, b, _descRec);
                localY += _descRec.Height + _linespace;
            }

            Control.ItemPaint(g, localX, localY);
        }

        private void SetupPanel()
        {
            int width = GetWidth();
            int localY = Style.PaddingTop;

            ScreenResolution screen = XFGraphics.GetScreenResolution();
            int height;

            switch (screen)
            {
                case ScreenResolution.VGA:
                    height = 470;
                    break;

                case ScreenResolution.WVGA:
                    height = 620;
                    break;

                case ScreenResolution.QVGA:
                    height = 220;
                    break;

                default:
                    height = 170;
                    break;
            }

            height -= GetHeight();
            int itmsHeight = 0;
            var items = new List<SenseItem>();
            foreach (var itm in Options.Select(opt => new SenseItem { MainText = opt }))
            {
                itm.Style.BackgroundColor = Color.White;
                items.Add(itm);
                itmsHeight += itm.GetHeight();
            }

            height = height > itmsHeight ? itmsHeight : height;
            int controlWidth = Control.GetWidth() - (Style.PaddingLeft + Style.PaddingRight);
            int xCont = (width - controlWidth) >> 1;
            int yCont = localY + Control.GetHeight();

            var rec = new Rectangle(xCont, yCont, controlWidth, height);
            _dropDownContainer.Bounds = rec;
            _dropDownPanel.Width = controlWidth;
            _dropDownPanel.Height = height;

            _dropDownPanel.ClearItems();
            foreach (var item in items)
                _dropDownPanel.Add(item);
        }

        public override XFItemClickResult GetClickResult()
        {
            if (_dropDownOpen)
                ((XFPanelList)Parent).OnBlur();
            else
                _dropDownOpen = true;
            return XFItemClickResult.Nothing;
        }

        public override void Dispose()
        {
            base.Dispose();
            if (Control != null)
                Control.Dispose();

            if (_dropDownPanel != null)
                _dropDownPanel.Dispose();

            if(_dropDownContainer != null)
                _dropDownContainer.Dispose();
        }

        public void Select(int index)
        {
            if (Options.Count <= index) return;
            Selected = Options[index];
            if (SelectionChanged != null)
                SelectionChanged(this, new TextEventArgs(Selected));
        }
    }

    public class SenseDropDownPanel : XFPanelList
    {
        #region Delegates

        public delegate void TextEventHandler(object sender, TextEventArgs args);

        #endregion

        public SenseDropDownPanel(Rectangle rec)
        {
            Width = rec.Width;
            Height = rec.Height;
        }

        public event TextEventHandler OnSelection;

        protected override void OnPaint(PaintEventArgs e)
        {
            displayScroll();

            onPaintInit(e);

            if (_offBitmap == null) //Bitmap for doublebuffering  
            {
                _offBitmap = new Bitmap(Width, Height);//XFBitmapFactory.GetBitmap(Width, Height);
            }
            using (Graphics g = Graphics.FromImage(_offBitmap))
            {
                PanelPaint(g);

                if (_scrollbar != null)
                {
                    _scrollbar.UpdatePanel(this);
                    _scrollbar.PaintScroll(g);
                }
            }
            e.Graphics.DrawImage(_offBitmap, 0, 0);
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            if (_curState == States.Click && OnSelection != null)
            {
                OnSelection(this, new TextEventArgs(_selected.ToString()));
            }
            base.OnMouseUp(e);
        }
    }
}